package com.pimee.web;

import java.beans.PropertyEditorSupport;
import java.io.IOException;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.UnauthorizedException;
import org.apache.shiro.mgt.RealmSecurityManager;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Maps;
import com.pimee.common.core.support.HttpCode;
import com.pimee.common.exception.BusinessException;
import com.pimee.common.exception.IllegalParameterException;
import com.pimee.common.util.DateUtil;
import com.pimee.common.util.StringUtils;
import com.pimee.common.util.shiro.ShiroUtils;
import com.pimee.model.SysUser;
import com.pimee.support.shiro.realm.AdminShiroRealm;

/**
 * 控制器状态基类
 * 
 * @author Bruce Shaw 2020年1月17日 上午11:25:30
 *
 */
public abstract class AbstractController {

	/**
	 * 日志对象
	 */
	protected final Logger logger = LogManager.getLogger(this.getClass());

	/**
	 * 获取登录名称
	 * 
	 * @return
	 */
	protected String getLoginName() {
		return ShiroUtils.getLoginName();
	}

	/**
	 * 获取用户id
	 * 
	 * @return
	 */
	protected Long getUserId() {
		return ShiroUtils.getUserId();
	}

	/**
	 * 获取用户
	 * 
	 * @return
	 */
	protected SysUser getSysUser() {
		return ShiroUtils.getSysUser();
	}

	/**
	 * 清缓存
	 */
	protected void clearCachedAuthorizationInfo() {
		RealmSecurityManager rsm = (RealmSecurityManager) SecurityUtils.getSecurityManager();
		AdminShiroRealm realm = (AdminShiroRealm) rsm.getRealms().iterator().next();
		realm.clearCachedAuthorizationInfo();
	}

	/**
	 * 将前台传递过来的日期格式的字符串，自动转化为Date类型
	 */
	@InitBinder
	public void initBinder(WebDataBinder binder) {
		// Date 类型转换
		binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
			@Override
			public void setAsText(String text) {
				setValue(DateUtil.parseDate(text));
			}
		});
	}

	/** 设置成功响应代码 */
	protected ResponseEntity<ModelMap> setSuccessModelMap(ModelMap modelMap) {
		return setSuccessModelMap(modelMap, null);
	}

	/** 设置成功响应代码 */
	protected ResponseEntity<ModelMap> setSuccessModelMap(ModelMap modelMap, Object data) {
		return setModelMap(modelMap, HttpCode.OK, data);
	}

	/** 设置响应代码 */
	protected ResponseEntity<ModelMap> setModelMap(ModelMap modelMap, HttpCode code) {
		return setModelMap(modelMap, code, null);
	}

	/** 设置响应代码 */
	protected ResponseEntity<ModelMap> setModelMap(ModelMap modelMap, HttpCode code, Object data) {
		Map<String, Object> map = Maps.newLinkedHashMap();
		map.putAll(modelMap);
		modelMap.clear();
		for (Iterator<String> iterator = map.keySet().iterator(); iterator.hasNext();) {
			String key = iterator.next();
			if (!key.startsWith("org.springframework.validation.BindingResult") && !key.equals("void")) {
				modelMap.put(key, map.get(key));
			}
		}
		if (data != null) {
			if (data instanceof PageInfo) {
				PageInfo<?> page = (PageInfo<?>) data;
				modelMap.put("rows", page.getList());
				modelMap.put("total", page.getTotal());
			} else {
				modelMap.put("data", data);
			}
		}
		modelMap.put("code", code.value().toString());
		modelMap.put("msg", code.msg());
		modelMap.put("timestamp", System.currentTimeMillis());
		return ResponseEntity.ok(modelMap);
	}

	/** 异常处理 */
	@ExceptionHandler(Exception.class)
	public void exceptionHandler(HttpServletRequest request, HttpServletResponse response, Exception ex)
			throws Exception {
		logger.error("", ex);
		ModelMap modelMap = new ModelMap();
		if (ex instanceof BusinessException) {
			BusinessException busiException = (BusinessException) ex;
			modelMap.put("code", busiException.getCode());
			modelMap.put("msg", busiException.getMsg());
		} else if (ex instanceof IllegalArgumentException) {
			IllegalParameterException paramException = (IllegalParameterException) ex;
			modelMap.put("code", paramException.getCode());
			modelMap.put("msg", paramException.getMsg());
		} else if (ex instanceof UnauthorizedException) {
			modelMap.put("code", HttpCode.FORBIDDEN.value().toString());
			modelMap.put("msg", StringUtils.defaultIfBlank(ex.getMessage(), HttpCode.FORBIDDEN.msg()));
		} else if (ex instanceof DuplicateKeyException) {
			modelMap.put("code", HttpCode.INTERNAL_SERVER_ERROR.value().toString());
			modelMap.put("msg", "存在相同的记录");
		} else {
			modelMap.put("code", HttpCode.INTERNAL_SERVER_ERROR.value().toString());
			String msg = StringUtils.defaultIfBlank(ex.getMessage(), HttpCode.INTERNAL_SERVER_ERROR.msg());
			modelMap.put("msg", msg.length() > 100 ? "系统异常,请稍候再试." : msg);
		}
		response.setContentType("application/json;charset=UTF-8");
		modelMap.put("timestamp", System.currentTimeMillis());
		logger.info("===> exceptionHandler RESPONSE : " + JSON.toJSON(modelMap));
		byte[] bytes = JSON.toJSONBytes(modelMap, SerializerFeature.DisableCircularReferenceDetect);
		response.getOutputStream().write(bytes);
	}

	/**
	 * 客户端返回JSON字符串
	 *
	 * @param response
	 * @param object
	 * @return
	 */
	protected String renderString(HttpServletResponse response, Object object) {
		return renderString(response, JSONObject.toJSONString(object), "application/json");
	}

	/**
	 * 客户端返回字符串
	 *
	 * @param response
	 * @param string
	 * @return
	 */
	protected String renderString(HttpServletResponse response, String string) {
		try {
			response.setCharacterEncoding("utf-8");
			response.getWriter().print(string);
			return null;
		} catch (IOException e) {
			return null;
		}
	}

	/**
	 * 客户端返回字符串
	 *
	 * @param response
	 * @param string
	 * @return
	 */
	protected String renderString(HttpServletResponse response, String string, String type) {
		try {
			response.reset();
			response.setContentType(type);
			response.setCharacterEncoding("utf-8");
			// 解决跨域问题
			response.setHeader("Access-Control-Allow-Origin", "*");
			response.getWriter().print(string);
			return null;
		} catch (IOException e) {
			return null;
		}
	}

	/**
	 * 页面跳转
	 */
	public String redirect(String url) {
		return StringUtils.format("redirect:{}", url);
	}
}
